#include "CreateParabolaWidget.h"

#include "Core/MainWindow.h"
#include <QMessageBox>
#include <vtkProperty.h>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include "FeatureShape/FeatureShape.h"

CreateParabolaWidget::CreateParabolaWidget(MainWindow* inMainWindow, ShapeOperation* inOperation, QWidget* parent)
	: QRWCreateCurveWidget(inMainWindow, inOperation, parent)
	, ui(new Ui::CreateParabolaWidgetClass())
{
	ui->setupUi(this);

	ui->vertexWidget->installEventFilter(this);
	ui->axisWidget->installEventFilter(this);
	ui->directrixWidget->installEventFilter(this);

	ui->vertexWidget->setStyleSheet("background-color:rgb(255,178,102)");

	m_vertexPnt = new RWTripleFloatInput(ui->vertexX, ui->vertexY, ui->vertexZ);
	m_axisVec = new RWTripleFloatInput(ui->axisX, ui->axisY, ui->axisZ);
	m_directrixVec = new RWTripleFloatInput(ui->directrixX, ui->directrixY, ui->directrixZ);

	m_mainWindow->SetSelectionMode(SM_Vertex);

	connect(ui->confirm, &QPushButton::clicked, this, &CreateParabolaWidget::onConfirm);
	connect(ui->cancel, &QPushButton::clicked, this, &CreateParabolaWidget::close);
	connect(ui->modify, &QPushButton::clicked, this, &CreateParabolaWidget::onApply);

	connect(ui->vertexX, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->vertexY, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->vertexZ, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->axisX, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->axisY, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->axisZ, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->directrixX, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->directrixY, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->directrixZ, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->focal, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->startLen, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);
	connect(ui->endLen, &QDoubleSpinBox::valueChanged, this, &CreateParabolaWidget::onPosChanged);


	// operation -> param
	if (inOperation)
	{
		CreateShapeOperation* CreateOP = static_cast<CreateShapeOperation*>(inOperation);
		FeatureShapeParabola* ParabolaShape = static_cast<FeatureShapeParabola*>(CreateOP->m_featureShape.get());
		ui->focal->setValue(ParabolaShape->_focal);
		ui->startLen->setValue(ParabolaShape->_startLen);
		ui->endLen->setValue(ParabolaShape->_endLen);
		m_vertexPnt->SetValue(ParabolaShape->_axis.Location());
		m_axisVec->SetValue(ParabolaShape->_axis.XDirection());
		m_directrixVec->SetValue(ParabolaShape->_axis.YDirection());
	}

	cacheActor = m_mainWindow->createParabola(GetCurrentAxis().second, ui->focal->value(), ui->startLen->value(), ui->endLen->value());
}

CreateParabolaWidget::~CreateParabolaWidget()
{
	delete ui;
	delete m_vertexPnt;
	delete m_axisVec;
	delete m_directrixVec;
}

void CreateParabolaWidget::onPosChanged()
{
	// 批量修改
	if (bBatchChange)
	{
		return;
	}

	UpdateInner();
}

void CreateParabolaWidget::OnPickPosition(const gp_Pnt& inPosition)
{
	if (focusIndex != 0)
	{
		return;
	}

	bBatchChange = true;
	m_vertexPnt->SetValue(inPosition);
	bBatchChange = false;

	UpdateInner();
}

ShapeOperation* CreateParabolaWidget::GetOperation()
{
	ShapeOperation* op = new CreateShapeOperation(tr("抛物线"), cacheActor->m_featureShape);
	return op;
}

void CreateParabolaWidget::GenerateFeatureShapeForCacheActor()
{
	cacheActor->m_featureShape.reset(new FeatureShapeParabola(cacheActor->OccShape(), GetCurrentAxis().second, ui->focal->value(), ui->startLen->value(), ui->endLen->value()));
}

bool CreateParabolaWidget::eventFilter(QObject* obj, QEvent* event)
{
	QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
	if (event->type() == QEvent::MouseButtonPress && mouseEvent->button() == Qt::LeftButton)
	{
		if (obj == ui->vertexWidget && focusIndex != 0)
		{
			ui->vertexWidget->setStyleSheet("background-color:rgb(255,178,102)");
			ui->axisWidget->setStyleSheet("background-color: #FFFFFF;");
			ui->directrixWidget->setStyleSheet("background-color: #FFFFFF;");
			focusIndex = 0;
			m_mainWindow->SetSelectionMode(SM_Vertex);
		}
		if (obj == ui->axisWidget && focusIndex != 1)
		{
			ui->axisWidget->setStyleSheet("background-color:rgb(255,178,102)");
			ui->vertexWidget->setStyleSheet("background-color: #FFFFFF;");
			ui->directrixWidget->setStyleSheet("background-color: #FFFFFF;");
			focusIndex = 1;
			m_mainWindow->SetSelectionMode(SM_Edge);
		}
		if (obj == ui->directrixWidget && focusIndex != 2)
		{
			ui->directrixWidget->setStyleSheet("background-color:rgb(255,178,102)");
			ui->vertexWidget->setStyleSheet("background-color: #FFFFFF;");
			ui->axisWidget->setStyleSheet("background-color: #FFFFFF;");
			focusIndex = 2;
			m_mainWindow->SetSelectionMode(SM_Edge);
		}
	}

	return QObject::eventFilter(obj, event);
}

void CreateParabolaWidget::OnPickDirection(const gp_Vec& inDirection)
{
	bBatchChange = true;
	if (focusIndex == 1)
	{
		m_axisVec->SetValue(inDirection);
	}
	else if (focusIndex == 2)
	{
		m_directrixVec->SetValue(inDirection);
	}
	bBatchChange = false;
}

void CreateParabolaWidget::Reset()
{
	QRWCreateCurveWidget::Reset();

	m_vertexPnt->SetValue(gp_Pnt());
	m_axisVec->SetValue(gp_Dir(0, 0, 1));
	m_directrixVec->SetValue(gp_Dir(1, 0, 0));
	ui->focal->setValue(0.5);
	ui->startLen->setValue(1);
	ui->endLen->setValue(1);

	cacheActor = m_mainWindow->createParabola(GetCurrentAxis().second, ui->focal->value(), ui->startLen->value(), ui->endLen->value());
	onPosChanged();
}

void CreateParabolaWidget::UpdateInner()
{
	std::pair<bool, gp_Ax2> axis = GetCurrentAxis();
	if (!axis.first)
	{
		return;
	}

	cacheActor = m_mainWindow->UpdateParabolaActor(cacheActor, axis.second, ui->focal->value(), ui->startLen->value(), ui->endLen->value());
}

std::pair<bool, gp_Ax2> CreateParabolaWidget::GetCurrentAxis()
{
	std::pair<bool, gp_Ax2> res;
	gp_Dir xDir{ ui->axisX->value(), ui->axisY->value(), ui->axisZ->value() };
	gp_Dir yDir{ ui->directrixX->value(), ui->directrixY->value(), ui->directrixZ->value() };

	if (!IsNearlyZero(xDir.Dot(yDir)))
	{
		QMessageBox::warning(this, tr("Error"), tr("准线必须与对称轴垂直!!!"));
		res.first = false;
		return res;
	}

	gp_Dir zDir = xDir.Crossed(yDir);
	res.first = true;
	res.second = gp_Ax2(gp_Pnt(ui->vertexX->value(), ui->vertexY->value(), ui->vertexZ->value()), zDir, xDir);

	return res;
}
